import { watch, ref, Ref } from 'vue'
import { isFunction, getVal } from '@/utils'
import { ElTable } from 'element-plus'

const useSelection = (
  props: Record<string, any>,
  data: Ref<any[]>,
  selectedKeysChange: (row: any[]) => void
) => {
  const elTableRef = ref<InstanceType<typeof ElTable>>()

  const getRowKey = (row: any) =>
    isFunction(props.rowKey) ? props.rowKey(row) : getVal(row, props.rowKey)

  // 不需要多选框
  if (!props.selectedKeys) {
    return {
      elTableRef,
      handleSelectionChange: () => {},
      selectionRows: () => {}
    }
  }

  let selectKeys: any[] = []
  let selectKeysMap: Map<any, boolean> = new Map()
  const handleSelectionChange = (rows: any[]) => {
    selectKeys = rows.map(getRowKey)
    if (props.selectKeysKeep) {
      data.value.forEach((row) => {
        const key = getRowKey(row)
        if (selectKeys.includes(key)) {
          selectKeysMap.set(key, true)
        } else {
          selectKeysMap.delete(key)
        }
      })
      selectKeys = [...selectKeysMap.keys()]
    }
    if (selectedKeysChange) {
      selectedKeysChange(selectKeys)
    }
  }

  // 选中 rows
  const selectionRows = (rows: any[]) => {
    // nextTick(() => {
    if (!elTableRef.value) return

    elTableRef.value.clearSelection()
    rows.forEach((row) => {
      elTableRef.value?.toggleRowSelection(row, true)
    })
    // });
  }

  // 选中 selectKeys 对应的 rows
  const selectionSelectKeys = () => {
    const keys = props.selectedKeys || []

    if (!data.value?.length) return
    const rows = keys.length
      ? data.value.filter((row: any) => {
          const key = getRowKey(row)
          return keys.includes(key)
        })
      : []

    selectionRows(rows)
    // 没有与selectKeys匹配的rows, 手动触发
    if (keys.length && !rows.length) {
      handleSelectionChange([])
    }
    return rows
  }

  watch(
    () => props.selectedKeys,
    () => {
      if (props.selectedKeys?.join() === selectKeys.join()) return

      if (props.selectKeysKeep) {
        selectKeysMap = new Map()
        props.selectKeys?.forEach((key: number) => selectKeysMap.set(key, true))
      }

      selectionSelectKeys()
    },
    {
      immediate: true
    }
  )

  // data更新/http重新执行，重新匹配选中项
  watch(() => data.value, selectionSelectKeys)

  return {
    elTableRef,
    handleSelectionChange,
    selectionRows
  }
}

export { useSelection }
